package spring

import (
	"ry/kernel"
	//"ry/vec"
	"ry/mat"
	//	"math"
	//	"fmt"
	"image"
)

type Agent interface {
	Update (m mat.Grid, dt float64)
	Init ()
	Wrap ()
	Round () (i,j int)
}

type Cell interface {
	Update (m mat.Grid, dt float64)
	Init (i,j int)
	Color () image.Color
}

type Model struct {
	Cells []Cell
	Grid mat.Grid
	Agents  []Agent
	R int
}

func (m *Model) InitAgents() {

	for k, _ := range m.Agents {
		m.Agents[k].Init ()
		m.Agents[k].Wrap()
	}
}

func (m *Model) InitCells() {

	rows, cols := m.Grid.Dims ()
	
	for i := 0; i < rows; i++ {
		for j := 0; j < cols; j++ {
			m.Cells [m.Grid.Index (i,j)].Init (i,j)
		}
	}
}

func (m *Model) UpdateAgents() {

	for k, a := range m.Agents {
		i,j := a.Round ()
		m.Agents[k].Update(m.Grid.Select(i-m.R,j-m.R,i+m.R,j+m.R), 1.0)
	}
}

func abs(i int) int {

	if i < 0 {
		return -i
	}

	return i
}

func (m *Model) UpdateCells() {

	//buf := m.Medium.Copy()

	rows, cols := m.Grid.Dims ()
	

	done := kernel.Launch (rows, cols, 
		func (i,j int) bool {
			m.Cells[m.Grid.Index (i,j)].Update (m.Grid.Select (i-m.R,j-m.R, i+m.R,j+m.R), 1.0)
			return true
		})
		
	_ = <-done
	
//	m.Medium.CopyFrom (buf)
}

func (m *Model) Draw(out *image.RGBA64) {

	rows, cols := m.Grid.Dims ()
	
	for i := 0; i < rows; i++ {
		for j := 0; j < cols; j++ {
			out.Set (i,j, m.Cells [m.Grid.Index (i,j)].Color ())
		}
	}
	
	white := image.RGBAColor{255,255,255,255}
	
	for k := 0; k < len (m.Agents); k++ {
		i,j := m.Agents [k].Round ()
		out.Set (i,j, white)
	}
}


